#include "flag.h"

void main(int argc, char ** argv)
{
	// Initialize OpenGL context.
	if(initGL(argc, argv) == false)
		return;

	// Initialize the VBO.
	initVBOs();

	// Register callbacks.
	glutDisplayFunc(display);
	glutKeyboardFunc(keyboard);

	// Compute the positions.
	run_initMasses(prev_pos, cur_pos, springs, WIDTH, HEIGHT, PAS, vbo_shaded);

	//display();

	glutTimerFunc(1, &timer1, 0);
	glutTimerFunc(1, &timer2, 0);

	// Start rendering mainloop
    glutMainLoop();
}

bool initGL(int argc, char ** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(window_width, window_height);
	glutCreateWindow("Flag 2.0");

	// default initialization
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glDisable(GL_DEPTH_TEST);

	// viewport
	glViewport(0, 0, window_width, window_height);

	// projection
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(F_LEFT, F_RIGHT, F_BOTTOM, F_TOP, F_NEAR, F_FAR);

	return true;
}

void initVBOs()
{
	// Generate the VBOs
	glGenBuffers(1, &vbo_shaded);
	//glGenBuffers(1, &vbo_wireframe);
	//glGenBuffers(1, &vbo_springs);

	// Initialize the VBOs
	glBindBuffer(GL_ARRAY_BUFFER, vbo_shaded);
		unsigned int size = 2 * WIDTH * (HEIGHT - 1) * sizeof(float3);
		float * data = (float *)malloc(size);
		glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW);
		free(data);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

	/*glBindBuffer(GL_ARRAY_BUFFER, vbo_wireframe);
		size = 2 * ((WIDTH * (HEIGHT - 1)) + (2 * HEIGHT * (WIDTH - 1)) - (WIDTH - 1)) * sizeof(float3);
		data = (float *)malloc(size);
		glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW);
		free(data);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindBuffer(GL_ARRAY_BUFFER, vbo_springs);
		//size = 2 * ((WIDTH * (HEIGHT - 1)) + (HEIGHT * (WIDTH - 1))) * sizeof(float3);
		size = 8 * WIDTH * HEIGHT * sizeof(float3);
		data = (float *)malloc(size);
		glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW);
		free(data);
    glBindBuffer(GL_ARRAY_BUFFER, 0);*/
}

void keyboard(unsigned char key, int x, int y)
{
	switch(key)
	{
		case ' ':
			pause = !pause;
			if(!pause)
			{
				glutTimerFunc(1, &timer1, 0);
				glutTimerFunc(1, &timer2, 0);
			}
			break;
		case 'd':
			if(dsp < SPRINGS)
				dsp++;
			else
				dsp = SHADED;
			break;
		case 'D':
			if(dsp > SHADED)
				dsp--;
			else
				dsp = SPRINGS;
			break;
		case KEY_ESC:
			exit(0);
			break;
		default:
			printf("Key %d pressed\n", key);
	}
}

void timer1(int step)
{
	if(pause)
		return;
	
	glutTimerFunc(LATENCE1, &timer1, ++step1);

	glutPostRedisplay();

	if(step % 25 == 0)
		printf("Display %d\n", step1);
}

void timer2(int step)
{
	if(pause)
		return;
	
	glutTimerFunc(LATENCE2, &timer2, ++step2);

	/*switch(dsp)
	{
		case SHADED:*/
			run_computeFlag(prev_pos, cur_pos, springs, WIDTH, HEIGHT, GRAVITY, FRICTION, FACT_L_MAX, dsp, vbo_shaded);
			/*break;
		case WIREFRAME:
			run_computeFlag(prev_pos, cur_pos, springs, WIDTH, HEIGHT, GRAVITY, dsp, vbo_wireframe);
			break;
		case SPRINGS:
			run_computeFlag(prev_pos, cur_pos, springs, WIDTH, HEIGHT, GRAVITY, dsp, vbo_springs);
			break;
		default:
			break;
	}*/

	if(step % 25 == 0)
		printf("Compute %d\n", step2);
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Set view matrix.
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // Render from the vbo.
	glPushMatrix();
		glTranslatef(-600.0, -125.0, -10.0);
		/*switch(dsp)
		{
			case SHADED:*/
				glBindBuffer(GL_ARRAY_BUFFER, vbo_shaded);
				glVertexPointer(3, GL_FLOAT, 0, 0);
				glEnableClientState(GL_VERTEX_ARRAY);
				glColor3f(1.0, 1.0, 1.0);
				for(int i = 0, size = WIDTH * 2; i < HEIGHT - 1; i++)
					glDrawArrays(GL_TRIANGLE_STRIP, i * size, size);
				glDisableClientState(GL_VERTEX_ARRAY);
				/*break;
			case WIREFRAME:
				glBindBuffer(GL_ARRAY_BUFFER, vbo_wireframe);
				glVertexPointer(3, GL_FLOAT, 0, 0);
				glEnableClientState(GL_VERTEX_ARRAY);
				glColor3f(1.0, 1.0, 1.0);
				for(int i = 0, size = WIDTH * 2; i < HEIGHT - 1; i++)
					glDrawArrays(GL_LINE_STRIP, i * size, size);
				glDisableClientState(GL_VERTEX_ARRAY);
				break;
			case SPRINGS:
				glBindBuffer(GL_ARRAY_BUFFER, vbo_springs);
				glVertexPointer(3, GL_FLOAT, 0, 0);
				glEnableClientState(GL_VERTEX_ARRAY);
				glColor3f(1.0, 1.0, 1.0);
				glDrawArrays(GL_LINES, 0, 8 * WIDTH * HEIGHT);
				glDisableClientState(GL_VERTEX_ARRAY);
				break;
			default:
				break;
		}*/
	glPopMatrix();

    glutSwapBuffers();
    glutPostRedisplay();
}

